package model

import (
	"context"
	"fmt"
	"strings"

	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ MenuModel = (*customMenuModel)(nil)

type (
	// MenuModel is an interface to be customized, add more methods here,
	// and implement the added methods in customMenuModel.
	MenuModel interface {
		menuModel
		withSession(session sqlx.Session) MenuModel
		FindUserMenu(ctx context.Context, ids []int64, isSuperAdmin bool) ([]Menu, error)
		FindMenuPage(ctx context.Context, offset int, size int) ([]Menu, error)
		FindMenuCount(ctx context.Context) (int, error)
		FindUserMenuOptions(ctx context.Context, id int64) ([]Menu, error)
	}

	customMenuModel struct {
		*defaultMenuModel
	}
)

func (m *customMenuModel) FindUserMenuOptions(ctx context.Context, id int64) ([]Menu, error) {
	query := fmt.Sprintf("select %s from %s ", menuRows, m.table)
	var menus []Menu
	err := m.conn.QueryRowsCtx(ctx, &menus, query)
	if err != nil {
		return nil, err
	}
	return menus, nil
}

func (m *customMenuModel) FindMenuCount(ctx context.Context) (int, error) {
	query := fmt.Sprintf("select count(*) from %s", m.table)
	var count int
	err := m.conn.QueryRowCtx(ctx, &count, query)
	if err != nil {
		return 0, err
	}
	return count, err
}

func (m *customMenuModel) FindMenuPage(ctx context.Context, offset int, size int) ([]Menu, error) {
	query := fmt.Sprintf("select %s from %s limit  ?,? ", menuRows, m.table)
	var menus []Menu
	err := m.conn.QueryRowsCtx(ctx, &menus, query, offset, size)
	if err != nil {
		return nil, err
	}
	return menus, nil
}

func (m *customMenuModel) FindUserMenu(ctx context.Context, ids []int64, isSuperAdmin bool) ([]Menu, error) {
	var query string
	var menus []Menu

	if isSuperAdmin {
		// 超级管理员查询所有菜单
		query = fmt.Sprintf("select %s from %s", menuRows, m.table)
		_ = m.conn.QueryRowsCtx(ctx, &menus, query)
	} else {
		// 普通用户根据角色ID查询菜单
		if len(ids) == 0 {
			return []Menu{}, nil
		}

		placeholders := strings.Repeat("?,", len(ids)-1) + "?"
		query = fmt.Sprintf("select %s from %s where id in (%s)", menuRows, m.table, placeholders)

		args := make([]interface{}, len(ids))
		for i, id := range ids {
			args[i] = id
		}

		err := m.conn.QueryRowsCtx(ctx, &menus, query, args...)
		if err != nil {
			return nil, err
		}
	}
	return menus, nil
}

// NewMenuModel returns a model for the database table.
func NewMenuModel(conn sqlx.SqlConn) MenuModel {
	return &customMenuModel{
		defaultMenuModel: newMenuModel(conn),
	}
}

func (m *customMenuModel) withSession(session sqlx.Session) MenuModel {
	return NewMenuModel(sqlx.NewSqlConnFromSession(session))
}
